package user

import (
	"context"
	"database/sql"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"git.mycaigou.com/gfyx/common/tenant_db"
	"git.mycaigou.com/gfyx/common/usermetadata"
	"git.mycaigou.com/gfyx/micro-gfyx-oppty-service/infrastructure/common/constants"
	"git.mycaigou.com/gfyx/micro-gfyx-oppty-service/infrastructure/common/errcode"
	"git.mycaigou.com/gfyx/micro-gfyx-oppty-service/infrastructure/common/utils"
	"git.mycaigou.com/gfyx/micro-gfyx-oppty-service/infrastructure/common/utils/auth"
	"git.mycaigou.com/gfyx/micro-gfyx-oppty-service/infrastructure/dto/base"
	"git.mycaigou.com/gfyx/micro-gfyx-oppty-service/infrastructure/repository/base/org"
	"git.mycaigou.com/gfyx/micro-gfyx-oppty-service/infrastructure/repository/base/profit"
	"git.mycaigou.com/gfyx/micro-gfyx-oppty-service/infrastructure/repository/base/role"
	"git.mycaigou.com/gfyx/micro-gfyx-oppty-service/infrastructure/repository/base/user"
	"git.mycaigou.com/gfyx/micro-gfyx-oppty-service/infrastructure/repository/remote/gfyx_user_service_remote"
	basePb "git.mycaigou.com/gfyx/micro-gfyx-oppty-service/proto/micro_gfyx_oppty_service_proto/micro-gfyx-oppty-service/base"
	micro_gfyx_user_service "git.mycaigou.com/gfyx/micro-gfyx-oppty-service/proto/micro_gfyx_user_service_proto/micro-gfyx-user-service"
	"git.myscrm.cn/golang/common/ykerrcode"
	"git.myscrm.cn/golang/stark/v4"
	"github.com/google/uuid"
	"gorm.io/gorm"
	"strings"
	"time"
)

type userService struct {
	orgRepo             org.OrgRepositoryIface
	userOrgRepo         user.UserOrgRepositoryIface
	userRepo            user.UserRepositoryIface
	userRoleRepo        user.UserRoleRepositoryIface
	roleRepo            role.RoleRepositoryIface
	userBehaviorRepo    user.UserBehaviorRepositoryIface
	profitRepo          profit.ProfitRepositoryIface
	gfyxUserServiceRepo gfyx_user_service_remote.GfyxUserServiceRepositoryIface
}

// NewUserService 构造函数
func NewUserService(
	orgRepo org.OrgRepositoryIface,
	userOrgRepo user.UserOrgRepositoryIface,
	userRepo user.UserRepositoryIface,
	userRoleRepo user.UserRoleRepositoryIface,
	userBehaviorRepo user.UserBehaviorRepositoryIface,
	roleRepo role.RoleRepositoryIface,
	gfyxUserServiceRepo gfyx_user_service_remote.GfyxUserServiceRepositoryIface,
	profitRepo profit.ProfitRepositoryIface) UserServiceIface {
	return &userService{
		orgRepo:             orgRepo,
		userOrgRepo:         userOrgRepo,
		userRepo:            userRepo,
		userRoleRepo:        userRoleRepo,
		roleRepo:            roleRepo,
		userBehaviorRepo:    userBehaviorRepo,
		profitRepo:          profitRepo,
		gfyxUserServiceRepo: gfyxUserServiceRepo,
	}
}

// UserList 账号列表
func (s *userService) UserList(ctx context.Context, orgId int64, status int32, keyword string, page *utils.PageInfo) ([]*user.GfyxUserPo, *utils.PageInfo, error) {
	// 1. 检查部门是否存在
	orgObj, err := s.orgRepo.GetById(ctx, orgId)
	if err != nil {
		return nil, nil, err
	}

	if (orgObj == nil) || (orgObj.Id == 0) {
		return nil, nil, errcode.OrgDataNotExist
	}

	// 2. 获取该部门下的所有子部门
	orgIds, err := s.orgRepo.GetAllSubOrg(ctx, orgId)
	orgIds = append(orgIds, orgId)
	fmt.Printf("============orgIds: %+v", orgIds)
	if err != nil {
		return nil, nil, err
	}

	// 3. 获取这些部门下的所有用户，租户用户体量小于1000时问题都不大
	userOrgList, err := s.userOrgRepo.GetAllUsersByOrgId(ctx, orgIds)
	if err != nil {
		return nil, nil, err
	}

	userIds := make([]int64, 0)
	for _, user := range userOrgList {
		userIds = append(userIds, user.UserId)
	}

	if len(userIds) == 0 {
		return []*user.GfyxUserPo{}, &utils.PageInfo{}, nil
	}

	// 4. 检索用户信息
	list, page, err := s.userRepo.UserList(ctx, userIds, status, keyword, page)
	if err != nil {
		return nil, nil, err
	}

	return list, page, nil
}

// UserSave 新增/修改账号信息
func (s *userService) UserSave(ctx context.Context, userObj *user.GfyxUserPo, orgIds []int64, roleIds []int64) (int64, error) {
	if userObj == nil {
		return 0, errors.New("参数为空")
	}

	// 用户权益数判断
	if userObj.Id == 0 { // 编辑用户不校验用户数权益 #ID1277085
		profitAccountTotal, remainingUserCount, err := s.GetRemainingUserCount(ctx)
		if err != nil {
			return 0, err
		}
		if remainingUserCount <= 0 {
			return 0, errors.New(fmt.Sprintf("授权用户数共%d个，当前已添加用户%d个，无法继续添加", profitAccountTotal, (profitAccountTotal - remainingUserCount)))
		}
	}

	// 检查用户是否存在
	if userObj.Id != 0 {
		userInfo, err := s.userRepo.UserDetailByUserId(ctx, userObj.Id)
		if err != nil {
			return 0, err
		} else if userInfo == nil || userInfo.Id != userObj.Id {
			return 0, errcode.UserNotExist
		}
		userObj.Uid = userInfo.Uid
		if userObj.Status == 0 {
			userObj.Status = userInfo.Status
		}
		if userObj.Account == "" {
			userObj.Account = userInfo.Account
		}
	}

	// 1. 检查手机号是否已存在
	checkUser, err := s.userRepo.GetUserByAccountOrMobile(ctx, userObj.Mobile)
	if err != nil {
		return 0, err
	}
	if (checkUser != nil) && (checkUser.Id != 0) && (checkUser.Id != userObj.Id) {
		return 0, errcode.UserMobileExist
	}

	// 2. 检查组织机构是否存在
	orgList, err := s.orgRepo.ListByOrgIds(ctx, orgIds)
	if err != nil {
		return 0, err
	}
	orgListLen := len(orgList)
	if (orgListLen == 0) || (len(orgIds) != orgListLen) {
		return 0, errcode.OrgDataNotExist
	}

	// 获取组织的guid
	orgGuids := make([]string, 0)
	for _, item := range orgList {
		orgGuids = append(orgGuids, item.Guid)
	}

	// 3. 检查角色是否存在
	roleList, err := s.roleRepo.RoleListByRoleIds(ctx, roleIds)
	if err != nil {
		return 0, err
	}
	roleListLen := len(roleList)
	if (roleListLen == 0) || (roleListLen != len(roleIds)) {
		return 0, errcode.RoleDataNotExist
	}

	if userObj.Id == 0 {
		if (userObj.Password == "") || (len(userObj.Password) < 8) || (len(userObj.Password) > 32) {
			return 0, errcode.UserPasswdInvalid
		}
		userObj.Password, userObj.Salt = auth.NewAuth().EncryptPassword(userObj.Password)
		userObj.Uid = uuid.New().String()
		userObj.Status = 1
	} else {
		if userObj.Password != "" {
			if (len(userObj.Password) < 8) || (len(userObj.Password) > 32) {
				return 0, errcode.UserPasswdInvalid
			}
			userObj.Password, userObj.Salt = auth.NewAuth().EncryptPassword(userObj.Password)
		}
	}
	userId, err := s.userRepo.SaveUserAll(ctx, userObj, roleIds, orgIds, orgGuids)
	stark.Logger.Infof(ctx,
		"UserSave-info, userObj: %+v, orgIds: %+v, roleIds: %+v, userId: %d, err: %+v",
		userObj, orgIds, roleIds, userId, err)
	if err != nil {
		return 0, err
	}

	// 同步用户到非租户用户（小程序用户）
	isDisable := false
	if userObj.Status != 0 {
		if userObj.Status == 1 {
			isDisable = false
		} else {
			isDisable = true
		}
	} else {
		if checkUser != nil {
			if checkUser.Status == 1 {
				isDisable = false
			} else {
				isDisable = true
			}
		}
	}

	buuid := ""
	if len(orgGuids) > 0 {
		buuid = orgGuids[0]
	}
	userCode := ""
	// 新增
	if userObj.Id == 0 {
		userCode = userObj.Mobile
	} else {
		if userObj.Account != "" {
			userCode = userObj.Account
		} else if (checkUser != nil) && (checkUser.Account != "") {
			userCode = checkUser.Account
		}
	}

	userList := []*micro_gfyx_user_service.IncrUser{
		{
			UserUid:     userObj.Uid,
			UserId:      userObj.Id,
			MobilePhone: userObj.Mobile,
			UserName:    userObj.Name,
			UserCode:    userCode,
			IsDisable:   isDisable,
			Password:    userObj.Password,
			BuGuid:      buuid,
		},
	}

	tenantCode, err := tenant_db.GetTenantCode(ctx)
	if err != nil {
		return 0, err
	}
	if tenantCode == "" {
		return 0, errors.New("UserSave 上下文租户号获取不到")
	}
	incrementSyncUserRequest := &micro_gfyx_user_service.IncrementSyncUserRequest{
		TenantCode: tenantCode,
		Operation:  "U",
		UserList:   userList,
	}
	_, err = s.gfyxUserServiceRepo.IncrementSyncUser(ctx, incrementSyncUserRequest)
	if err != nil {
		return 0, err
	}

	return userId, nil
}

// 导入用户
func (s *userService) ImportUsers(ctx context.Context, userList []*base.ImportUserDto) (*basePb.UserImportUsersResponse, error) {
	if userList == nil {
		return nil, errors.New("参数为空")
	}

	// 用户权益数判断
	profitAccountTotal, remainingUserCount, err := s.GetRemainingUserCount(ctx)
	if err != nil {
		return nil, err
	}
	if remainingUserCount <= 0 {
		return nil, errors.New(fmt.Sprintf("授权用户数共%d个，当前已添加用户%d个，无法继续添加", profitAccountTotal, (profitAccountTotal - remainingUserCount)))
	}
	addUserCount := len(userList)
	if int64(addUserCount) > remainingUserCount {
		return nil, errors.New(fmt.Sprintf("授权用户数共%d个, 剩余可添加授权用户数%d个，当前导入列表用户数%d个，无法导入", profitAccountTotal, remainingUserCount, addUserCount))
	}

	resp := &basePb.UserImportUsersResponse{}
	for _, userDto := range userList {
		userObj := &user.GfyxUserPo{}
		userMsg := &basePb.ImportUserMsg{}
		saveFlag := true

		// 用户来源为导入
		userObj.Source = 2
		userObj.LastSetPasswordTime = sql.NullTime{
			Valid: false,
		}
		userObj.CreatedOn = time.Now()
		userObj.CreatedBy = usermetadata.GetMetaUserInfo(ctx).UserName
		userObj.ModifiedOn = time.Now()
		userObj.ModifiedBy = usermetadata.GetMetaUserInfo(ctx).UserName
		userObj.Uid = uuid.New().String()
		userObj.Status = 1

		if userDto.UserName == "" {
			userMsg.UserName = "姓名不能为空"
			saveFlag = false
		}
		userObj.Name = userDto.UserName

		userObj.Position = userDto.Position
		// 邮箱 非必填
		if userDto.Email != "" {
			userObj.Email = userDto.Email
		}

		if (userDto.Passwd == "") || (len(userDto.Passwd) < 8) || (len(userDto.Passwd) > 32) {
			userMsg.Passwd = "密码应该为大于等于8位，小于32位"
			saveFlag = false
		} else {
			password := base64.StdEncoding.EncodeToString([]byte(userDto.Passwd))
			userObj.Password, userObj.Salt = auth.NewAuth().EncryptPassword(password)
		}

		if userDto.Mobile == "" {
			userMsg.Mobile = "手机号不能为空"
			saveFlag = false
		} else {
			checkUser, err := s.userRepo.GetUserByAccountOrMobile(ctx, userDto.Mobile)
			if err != nil && err != gorm.ErrRecordNotFound {
				stark.Logger.Errorf(ctx, "ImportUsers-GetUserByAccountOrMobile err:%+v", err)
				return nil, err
			}
			if (checkUser != nil) && (checkUser.Id != 0) {
				userMsg.Mobile = "手机号已存在"
				saveFlag = false
			}
		}
		userObj.Mobile = userDto.Mobile

		// 检查组织是否存在
		orgGuids := make([]string, 0)
		orgIds := make([]int64, 0)
		if len(userDto.OrgFullName) == 0 {
			userMsg.FullName = "所属组织不能为空"
			saveFlag = false
		} else {
			orgFullNameList := strings.Split(userDto.OrgFullName, ",")
			for _, orgFullName := range orgFullNameList {
				orgInfo, err := s.orgRepo.CheckFullNameV2(ctx, orgFullName)
				if err != nil && err != gorm.ErrRecordNotFound {
					stark.Logger.Errorf(ctx, "ImportUsers-CheckFullNameV2 err:%+v", err)
					return nil, err
				}
				if orgInfo == nil {
					userMsg.FullName += orgFullName + " 组织不存在，请检查组织名称\n"
					saveFlag = false
				} else {
					orgGuids = append(orgGuids, orgInfo.Guid)
					orgIds = append(orgIds, orgInfo.Id)
				}
			}
		}

		// 检查角色是否存在
		roleIds := make([]int64, 0)
		if userDto.Role == "" {
			userMsg.Role = "角色不能为空"
			saveFlag = false
		} else {
			roleList := strings.Split(userDto.Role, ",")
			for _, role := range roleList {
				roleInfo, err := s.roleRepo.GetByRoleName(ctx, role)
				if err != nil {
					stark.Logger.Errorf(ctx, "ImportUsers-GetByRoleName err:%+v", err)
					return nil, err
				}
				if roleInfo.Id == 0 {
					userMsg.Role = role + " 角色不存在，请检查角色名称\n"
					saveFlag = false
				} else {
					roleIds = append(roleIds, roleInfo.Id)
				}
			}
		}

		if saveFlag {
			userId, err := s.userRepo.SaveUserAll(ctx, userObj, roleIds, orgIds, orgGuids)
			stark.Logger.Infof(ctx, "ImportUsers-info, userObj: %+v, orgIds: %+v, roleIds: %+v, userId: %d, err: %+v", userObj, orgIds, roleIds, userId, err)
			if err != nil {
				stark.Logger.Errorf(ctx, "ImportUsers-info fail,userObj:%+v, err:%+v", userObj, err)
				userMsg.IsSuccess = false
				userMsg.UserName = "用户保存失败"
			} else {
				userMsg.IsSuccess = true
				// 添加组织区域权限逻辑
				if userDto.DepartmentHeader == 1 {
					for k, orgId := range orgIds {
						err = s.userOrgRepo.AppendDepartmentHeader(ctx, userId, orgId, userObj.Uid, orgGuids[k])
						if err != nil {
							stark.Logger.Errorf(ctx, "用户导入，AppendDepartmentHeader失败, err:%+v", err)
							userMsg.DepartmentHeader = "用户导入成功，但组织区域权限保存失败"
							userMsg.IsSuccess = false
						}
					}
				}

				// 同步用户到非租户用户（小程序用户）
				buuid := ""
				if len(orgGuids) > 0 {
					buuid = orgGuids[0]
				}
				userCode := ""
				// 新增
				userCode = userObj.Mobile
				userList := []*micro_gfyx_user_service.IncrUser{
					{
						UserId:      userId,
						UserUid:     userObj.Uid,
						MobilePhone: userObj.Mobile,
						UserName:    userObj.Name,
						UserCode:    userCode,
						IsDisable:   false,
						Password:    userObj.Password,
						BuGuid:      buuid,
					},
				}
				tenantCode, _ := tenant_db.GetTenantCode(ctx)
				if tenantCode == "" {
					stark.Logger.Error(ctx, "获取ImportUsers GetTenantCode无值")
				} else {
					incrementSyncUserRequest := &micro_gfyx_user_service.IncrementSyncUserRequest{
						TenantCode: tenantCode,
						Operation:  "U",
						UserList:   userList,
					}
					_, err = s.gfyxUserServiceRepo.IncrementSyncUser(ctx, incrementSyncUserRequest)
					if err != nil {
						stark.Logger.Error(ctx, "获取ImportUsers IncrementSyncUser 同步用户失败", incrementSyncUserRequest)
					}
				}
			}
		} else {
			userMsg.IsSuccess = false
		}
		resp.MsgList = append(resp.MsgList, userMsg)
	}

	return resp, nil
}

// UserDelete 删除账号
func (s *userService) UserDelete(ctx context.Context, userId int64) (int64, error) {
	userObj, err := s.userRepo.UserDetailByUserId(ctx, userId)
	if err != nil {
		return userId, err
	}

	if userObj == nil || userObj.Id == 0 {
		return 0, errcode.UserNotExist
	}

	if userObj.IsAdmin == 1 {
		return 0, errcode.NotAllowDelAdmin
	}

	_, err = s.userRepo.UserDelete(ctx, userId, userObj.Uid)
	stark.Logger.Infof(ctx, "UserDelete-info, userId; %d, err: %+v", userId, err)
	if err != nil {
		return 0, err
	}

	isDisable := false
	if userObj.Status != 0 {
		if userObj.Status == 1 {
			isDisable = false
		} else {
			isDisable = true
		}
	}
	// 同步给非租户库
	userList := []*micro_gfyx_user_service.IncrUser{
		{
			UserId:      userObj.Id,
			UserUid:     userObj.Uid,
			MobilePhone: userObj.Mobile,
			UserName:    userObj.Name,
			UserCode:    userObj.Account,
			IsDisable:   isDisable,
		},
	}
	tenantCode, err := tenant_db.GetTenantCode(ctx)
	if err != nil {
		return 0, err
	}
	if tenantCode == "" {
		return 0, errors.New("UserSave 上下文租户号获取不到")
	}
	incrementSyncUserRequest := &micro_gfyx_user_service.IncrementSyncUserRequest{
		TenantCode: tenantCode,
		Operation:  "D",
		UserList:   userList,
	}
	_, err = s.gfyxUserServiceRepo.IncrementSyncUser(ctx, incrementSyncUserRequest)
	if err != nil {
		return 0, err
	}

	return userId, nil
}

// UserForbid 禁用用户
func (s *userService) UserForbid(ctx context.Context, userId int64, status int32) (int64, error) {
	userObj, err := s.userRepo.UserDetailByUserId(ctx, userId)
	if err != nil {
		return userId, err
	}

	if userObj == nil || userObj.Id == 0 {
		return 0, errcode.UserNotExist
	}

	if userObj.IsAdmin == 1 {
		return 0, errcode.NotAllowForbiddenAdmin
	}

	_, err = s.userRepo.UserForbid(ctx, userId, userObj.Uid, status)
	stark.Logger.Infof(ctx, "UserForbid-info, userId; %d, err: %+v", userId, err)
	if err != nil {
		return 0, err
	}

	isDisable := false
	if status == 1 {
		isDisable = false
	} else {
		isDisable = true
	}
	// 同步给非租户库
	userList := []*micro_gfyx_user_service.IncrUser{
		{
			UserId:      userObj.Id,
			UserUid:     userObj.Uid,
			MobilePhone: userObj.Mobile,
			UserName:    userObj.Name,
			UserCode:    userObj.Account,
			IsDisable:   isDisable,
		},
	}
	tenantCode, err := tenant_db.GetTenantCode(ctx)
	if err != nil {
		return 0, err
	}
	if tenantCode == "" {
		return 0, errors.New("UserSave 上下文租户号获取不到")
	}
	incrementSyncUserRequest := &micro_gfyx_user_service.IncrementSyncUserRequest{
		TenantCode: tenantCode,
		Operation:  "U",
		UserList:   userList,
	}
	_, err = s.gfyxUserServiceRepo.IncrementSyncUser(ctx, incrementSyncUserRequest)
	if err != nil {
		return 0, err
	}

	return userId, nil
}

// UserAuthRoles 账号授权
func (s *userService) UserAuthRoles(ctx context.Context, userId int64, roleIds []int64) error {
	userObj, err := s.userRepo.UserDetailByUserId(ctx, userId)
	if err != nil {
		return err
	}

	if userObj == nil || userObj.Id == 0 {
		return errcode.UserNotExist
	}

	roleList, err := s.roleRepo.RoleListByRoleIds(ctx, roleIds)
	if err != nil {
		return err
	}

	if len(roleList) != len(roleIds) {
		return errcode.RoleDataNotExist
	}

	err = s.userRoleRepo.AddRoleForUser(ctx, userId, roleIds)

	stark.Logger.Infof(ctx, "UserAuthRoles-info, userId: %s, err: %+v", userId, roleIds)

	return err
}

// ListByUserIds 获取组织列表
func (s *userService) ListByUserIds(ctx context.Context, userIds []int64) (map[int64][]*org.GfyOrganizationPo, map[int64][]*user.GfyxUserOrganizationRelationPo, map[int64][]*role.GfyRolePo, error) {
	userOrgMap := make(map[int64][]*org.GfyOrganizationPo)
	userRoleMap := make(map[int64][]*role.GfyRolePo)
	orgIds := make([]int64, 0)
	orgToUserRelMap := make(map[int64][]*user.GfyxUserOrganizationRelationPo)
	userToOrgRelMap := make(map[int64][]*user.GfyxUserOrganizationRelationPo)

	if len(userIds) == 0 {
		return userOrgMap, userToOrgRelMap, userRoleMap, nil
	}

	userOrgList, err := s.userOrgRepo.GetListByUserIds(ctx, userIds)
	if err != nil {
		return nil, nil, nil, err
	}

	for _, uo := range userOrgList {
		orgIds = append(orgIds, uo.OrganizationId)

		// 1. 用户到组织mapping
		utor, ok1 := userToOrgRelMap[uo.UserId]
		if !ok1 {
			utor = make([]*user.GfyxUserOrganizationRelationPo, 0)
		}
		utor = append(utor, uo)
		userToOrgRelMap[uo.UserId] = utor

		// 2. 组织到用户mapping
		otur, ok := orgToUserRelMap[uo.OrganizationId]
		if !ok {
			otur = make([]*user.GfyxUserOrganizationRelationPo, 0)
		}
		otur = append(otur, uo)
		orgToUserRelMap[uo.OrganizationId] = otur
	}

	if len(orgIds) == 0 {
		return userOrgMap, userToOrgRelMap, userRoleMap, nil
	}

	orgList, err := s.orgRepo.ListByOrgIds(ctx, orgIds)
	if err != nil {
		return nil, nil, nil, err
	}

	orgListMap := make(map[int64]*org.GfyOrganizationPo, 0)
	for _, oItem := range orgList {
		orgListMap[oItem.Id] = oItem
	}

	for userId, item := range userToOrgRelMap {
		for _, uItem := range item {
			orgIm, ok1 := orgListMap[uItem.OrganizationId]
			if !ok1 {
				continue
			}

			userOrgMap[userId] = append(userOrgMap[userId], orgIm)
		}
	}

	// 获取用户角色ID
	list, err := s.userRoleRepo.GetRolesByUserIds(ctx, userIds)
	if err != nil {
		return nil, nil, nil, err
	}

	roleIds := make([]int64, 0)
	for _, roleItem := range list {
		roleIds = append(roleIds, roleItem.RoleId)
	}
	// 获取角色
	roleList, err := s.roleRepo.RoleListByRoleIds(ctx, roleIds)
	if err != nil {
		return nil, nil, nil, err
	}

	for _, userId := range userIds {
		userRoleMap[userId] = make([]*role.GfyRolePo, 0)
		for _, item := range list {
			if item.UserId == userId {
				for _, role := range roleList {
					if role.Id == item.RoleId {
						userRoleMap[userId] = append(userRoleMap[userId], role)
					}
				}
			}
		}
	}

	for userId, item := range userRoleMap {
		for _, uItem := range item {
			fmt.Printf("userId: %d | uItem: %#v\n", userId, uItem)
		}
	}

	return userOrgMap, userToOrgRelMap, userRoleMap, nil
}

// UserInfo 获取用户信息
func (s *userService) UserInfo(ctx context.Context, request basePb.UserInfoRequest) (*basePb.UserInfoResponse, error) {
	// 1. 查找用户是否存在
	userPo, err := s.userRepo.UserDetailByUserId(ctx, request.UserId)
	if err != nil {
		stark.Logger.Errorf(ctx, "Get UserInfo by id failed, id:%d, err:%+v", request.UserId, err)
		return nil, ykerrcode.TogRPCError(errcode.USER_ACCOUNT_NOT_EXISIT, "用户不存在")
	}
	resp := &basePb.UserInfoResponse{
		UserId:        userPo.Id,
		UserGuid:      userPo.Uid,
		Account:       userPo.Account,
		Name:          userPo.Name,
		Mobile:        userPo.Mobile,
		Email:         userPo.Email,
		Position:      userPo.Position,
		ResetPassword: 0,
	}

	// 如果用户没有设置过密码，或者 6 个月未更新过密码，则让客户重新修改密码
	if userPo.LastSetPasswordTime.Valid == false {
		resp.ResetPassword = 1
	}

	return resp, nil
}

// SetPassword 设置密码
func (s *userService) SetPassword(ctx context.Context, request basePb.ResetPasswordRequest) (*basePb.ResetPasswordResponse, error) {
	// 1. 查找用户是否存在
	userPo, err := s.userRepo.UserDetailByUserId(ctx, request.UserId)
	if err != nil {
		stark.Logger.Errorf(ctx, "Get UserInfo by id failed, id:%d, err:%+v", request.UserId, err)
		return nil, ykerrcode.TogRPCError(errcode.USER_ACCOUNT_NOT_EXISIT, "用户不存在")
	}

	if userPo == nil || userPo.Id == 0 {
		return nil, errcode.UserNotExist
	}

	// 2. 保存密码
	authUtil := auth.NewAuth()
	password, salt := authUtil.EncryptPassword(request.NewPassword)
	userPo.Salt = salt
	userPo.Password = password
	userPo.LastSetPasswordTime = sql.NullTime{
		Time:  time.Now(),
		Valid: true,
	}
	userPo.ModifiedOn = time.Now()
	userPo.ModifiedBy = userPo.Uid
	_, err = s.userRepo.SaveUser(ctx, userPo)
	if err != nil {
		stark.Logger.Errorf(ctx, "SaveTaskLog Password failed, id:%d, err:%+v", request.UserId, err)
		return nil, ykerrcode.TogRPCError(errcode.USER_SAVE_PASSWORD_ERROR, "设置密码失败")
	}

	// 3. 保存行为日志
	requestStr, _ := json.Marshal(request)
	userBehaviorPo := &user.GfyxUserBehaviorPo{
		Module:     user.ModuleUser,
		Action:     user.ActionSetPassword,
		UserID:     userPo.Uid,
		Token:      "",
		Method:     user.MethodSetPassword,
		Params:     string(requestStr),
		CreatedOn:  time.Now(),
		CreatedBy:  userPo.Uid,
		ModifiedOn: time.Now(),
		ModifiedBy: userPo.Uid,
		IsDeleted:  0,
	}
	_, err = s.userBehaviorRepo.SaveUserBehavior(ctx, userBehaviorPo)
	if err != nil {
		return nil, ykerrcode.TogRPCError(errcode.USER_LOGIN_SAVE_STATUS_ERROR, "保存密码失败")
	}

	return new(basePb.ResetPasswordResponse), nil
}

// UpdateAdminPassword 设置密码
func (s *userService) UpdateAdminPassword(ctx context.Context, request basePb.UpdateAdminPasswordRequest) (*basePb.UpdateAdminPasswordResponse, error) {
	account := "admin" //一般不会变
	// 1. 查找用户是否存在
	userPo, err := s.userRepo.UserDetailByAccount(ctx, account)
	if err != nil {
		stark.Logger.Errorf(ctx, "Get UserInfo by account failed, account:%d, err:%+v", account, err)
		return nil, ykerrcode.TogRPCError(errcode.USER_ACCOUNT_NOT_EXISIT, "用户不存在")
	}

	if userPo == nil || userPo.Id == 0 {
		return nil, errcode.UserNotExist
	}

	// 2. 保存密码
	passwordBase := base64.StdEncoding.EncodeToString([]byte(request.NewPassword))
	authUtil := auth.NewAuth()
	password, salt := authUtil.EncryptPassword(passwordBase)
	userPo.Salt = salt
	userPo.Password = password
	userPo.LastSetPasswordTime = sql.NullTime{
		Time:  time.Now(),
		Valid: true,
	}
	userPo.ModifiedOn = time.Now()
	userPo.ModifiedBy = userPo.Uid
	_, err = s.userRepo.SaveUser(ctx, userPo)
	if err != nil {
		stark.Logger.Errorf(ctx, "SaveTaskLog Password failed, account:%d, err:%+v", account, err)
		return nil, ykerrcode.TogRPCError(errcode.USER_SAVE_PASSWORD_ERROR, "设置密码失败")
	}

	// 3. 保存行为日志
	requestStr, _ := json.Marshal(request)
	userBehaviorPo := &user.GfyxUserBehaviorPo{
		Module:     user.ModuleUser,
		Action:     user.ActionSetPassword,
		UserID:     userPo.Uid,
		Token:      "",
		Method:     user.MethodSetPassword,
		Params:     string(requestStr),
		CreatedOn:  time.Now(),
		CreatedBy:  userPo.Uid,
		ModifiedOn: time.Now(),
		ModifiedBy: userPo.Uid,
		IsDeleted:  0,
	}
	_, err = s.userBehaviorRepo.SaveUserBehavior(ctx, userBehaviorPo)
	if err != nil {
		return nil, ykerrcode.TogRPCError(errcode.USER_LOGIN_SAVE_STATUS_ERROR, "保存密码失败")
	}

	return new(basePb.UpdateAdminPasswordResponse), nil
}

// UserDetail 用户详情
func (s *userService) UserDetail(ctx context.Context, userId int64) (*user.GfyxUserPo, []*org.GfyOrganizationPo, []*role.GfyRolePo, error) {
	userDetail, err := s.userRepo.UserDetailByUserId(ctx, userId)
	if err != nil {
		return nil, nil, nil, err
	}

	if userDetail == nil {
		return nil, nil, nil, errcode.UserNotExist
	}

	// 获取组织
	userOrgRelList, err := s.userOrgRepo.GetListByUserIds(ctx, []int64{userDetail.Id})
	if err != nil {
		return nil, nil, nil, err
	}

	orgIds := make([]int64, 0)
	for _, uor := range userOrgRelList {
		orgIds = append(orgIds, uor.OrganizationId)
	}

	orgList, err := s.orgRepo.ListByOrgIds(ctx, orgIds)
	if err != nil {
		return nil, nil, nil, err
	}

	// 获取角色
	list, err := s.userRoleRepo.GetRolesByUserIds(ctx, []int64{userId})
	if err != nil {
		return nil, nil, nil, err
	}

	roleIds := make([]int64, 0)
	for _, roleItem := range list {
		roleIds = append(roleIds, roleItem.RoleId)
	}

	roleList, err := s.roleRepo.RoleListByRoleIds(ctx, roleIds)
	if err != nil {
		return nil, nil, nil, err
	}

	return userDetail, orgList, roleList, nil
}

// SetDepartmentHeader 设置/取消负责人
func (s *userService) SetDepartmentHeader(ctx context.Context, userIds []int64, orgId int64) error {
	// 1. 检查用户
	userObjList, _, err := s.userRepo.UserList(ctx, userIds, 0, "", &utils.PageInfo{Page: 1, PageSize: 9999})
	if err != nil {
		return err
	}
	if userObjList == nil || len(userObjList) != len(userIds) {
		return errcode.UserNotExist
	}

	userGuidList := make([]string, 0)
	for _, item := range userObjList {
		userGuidList = append(userGuidList, item.Uid)
	}

	// 2. 检查部门
	orgObj, err := s.orgRepo.GetById(ctx, orgId)
	if err != nil {
		return err
	}
	if orgObj == nil || orgObj.Id == 0 {
		return errcode.OrgDataNotExist
	}

	err = s.userOrgRepo.SetDepartmentHeader(ctx, userIds, orgId, userGuidList, orgObj.Guid)
	stark.Logger.Infof(ctx, "SetDepartmentHeader-info: %+v, userId: %+v, orgId: %+v, responsibleType: %+v",
		err, userIds, orgId)
	return err
}

// ChangeUserStatusByProfitAccountNum 冻结或解冻用户，根据可用权益可用账号数量来调整
// 当用户数超过可用账号数时，冻结一部分用户账号，冻结场景为权益到期冻结
// 当用户数小于可用账号数时，解冻一部分因权益到期禁用的账号
func (s *userService) ChangeUserStatusByProfitAccountNum(ctx context.Context, accountNum int32) error {
	count, _, err := s.userRepo.QueryUserList(ctx,
		map[string]interface{}{"status": 1, "is_deleted": constants.IsDeletedFalse},
		&utils.PageInfo{Page: 1, PageSize: 1}, "id")
	if err != nil {
		return err
	}

	num := int32(count) - accountNum
	if num > 0 {
		// 找出需要冻结的用户
		_, userList, err := s.userRepo.QueryUserList(ctx,
			map[string]interface{}{"status": 1, "is_deleted": constants.IsDeletedFalse},
			&utils.PageInfo{Page: 1, PageSize: int(num)}, "id desc")
		if err != nil {
			return err
		}
		var ids []int64
		for _, userPo := range userList {
			ids = append(ids, userPo.Id)
		}
		if len(ids) > 0 {
			err = s.userRepo.UpdateUserByCondition(ctx, map[string]interface{}{"ids": ids},
				map[string]interface{}{"status": 2, "forbidden_scene": 1, "modified_on": time.Now()})
			if err != nil {
				return err
			}
		}
	} else if num < 0 {
		num = -num
		// 找出需要冻结的用户
		_, userList, err := s.userRepo.QueryUserList(ctx,
			map[string]interface{}{"status": 2, "forbidden_scene": 1, "is_deleted": constants.IsDeletedFalse},
			&utils.PageInfo{Page: 1, PageSize: int(num)}, "id")
		if err != nil {
			return err
		}
		var ids []int64
		for _, userPo := range userList {
			ids = append(ids, userPo.Id)
		}
		if len(ids) > 0 {
			err = s.userRepo.UpdateUserByCondition(ctx, map[string]interface{}{"ids": ids},
				map[string]interface{}{"status": 1, "forbidden_scene": 0, "modified_on": time.Now()})
			if err != nil {
				return err
			}
		}
	}

	return nil
}

// SyncUserForJM 同步建模的用户到新的用户表
func (s *userService) SyncUserForJM(ctx context.Context, request basePb.BaseOldUserSyncRequest) (*basePb.BaseOldUserSyncResponse, error) {
	// 如果数据为空，则直接返回
	if len(request.Users) <= 0 {
		return nil, ykerrcode.TogRPCError(errcode.USER_SYNC_NOT_FOUND_DATA, "同步数据为空")
	}

	// 如果操作是删除，则直接构建删除的数组，
	if request.Op == constants.JmSyncOoDel {
		var userGuids []string
		for _, v := range request.Users {
			if v.Uid != "" {
				userGuids = append(userGuids, v.Uid)
			}
		}
		if len(userGuids) < 0 {
			return nil, ykerrcode.TogRPCError(errcode.USER_SYNC_NOT_FOUND_DATA, "用户数据为空")
		}

		condition := map[string]interface{}{"guids": userGuids}
		updateFields := map[string]interface{}{"modified_by": "jm-sync", "modified_on": time.Now(), "is_deleted": constants.IsDeletedTrue}
		err := s.userRepo.UpdateUserByCondition(ctx, condition, updateFields)
		if err != nil {
			stark.Logger.Errorf(ctx, "UpdateUserByCondition,err:", err)
			return nil, ykerrcode.TogRPCError(errcode.USER_SYNC_DEL_ERROR, "删除用户失败")
		}
		// 删除用户组织关系
	} else {
		// 如果是增加或者更新，则先通过建模用户的 id 查询一遍，存在就更新，不存在就插入
		// 由于数据量不大就在 for 先查询，如果有瓶颈再切换
		var syncErr error
		for _, jmUser := range request.Users {
			// 查询用户数据
			userPo, syncErr := s.userRepo.GetUserByCondition(ctx, map[string]interface{}{"uid": jmUser.Uid})
			if syncErr != nil {
				stark.Logger.Errorf(ctx, "GetUserByCondition,err:", syncErr)
				continue
			}
			if userPo.Id <= 0 {
				// 创建逻辑
				userPo.Uid = jmUser.Uid
				userPo.CreatedBy = "jm-sync"
				userPo.CreatedOn = time.Now()
			}

			//if userPo.LastSetPasswordTime.IsZero() {
			//	userPo.LastSetPasswordTime = time.Now()
			//}

			userPo.Mobile = jmUser.Mobile
			userPo.Name = jmUser.Name
			userPo.Account = jmUser.Account
			userPo.Email = jmUser.Email
			userPo.Position = jmUser.Position
			userPo.Salt = jmUser.Salt
			userPo.Password = jmUser.Password
			userPo.Source = 3
			userPo.Status = jmUser.Status
			userPo.ModifiedBy = "jm-sync"
			userPo.ModifiedOn = time.Now()
			_, syncErr = s.userRepo.SaveUser(ctx, userPo)
			if syncErr != nil {
				continue
			}

			if jmUser.OrganizationUid != "" {
				// 处理组织关系
				// 使用 uid 查询组织是否存在
				orgPo, err := s.orgRepo.GetByUid(ctx, jmUser.OrganizationUid)
				if err != nil {
					continue
				}
				// 删除用户的组织关系，再重新插入
				_ = s.userOrgRepo.DeletedUserOrgRelation(ctx, userPo.Id)
				// 插入关系
				_ = s.userOrgRepo.SaveUserOrgRelation(ctx, &user.GfyxUserOrganizationRelationPo{
					UserId:         userPo.Id,
					OrganizationId: orgPo.Id,
					CreatedOn:      time.Now(),
					CreatedBy:      "jm-sync",
					ModifiedOn:     time.Now(),
					ModifiedBy:     "jm-sync",
					IsDeleted:      0,
				})
			}
		}

		if syncErr != nil {
			return nil, ykerrcode.TogRPCError(errcode.USER_SYNC_UPDATE_ERROR, "删除用户失败")
		}
	}

	return new(basePb.BaseOldUserSyncResponse), nil
}

func (s *userService) GetAllUser(ctx context.Context) (int32, []*user.GfyxUserPo, error) {
	count, list, err := s.userRepo.QueryUserList(ctx, map[string]interface{}{"is_deleted": constants.IsDeletedFalse, "status": 1}, nil, "")
	if err != nil {
		return 0, nil, err
	}

	return int32(count), list, nil
}

func (s *userService) GetRemainingUserCount(ctx context.Context) (int64, int64, error) {
	// 获取用户权益数
	profitAccount, err := s.profitRepo.QueryProfitAccount(ctx)
	if err != nil {
		return 0, 0, err
	}
	if profitAccount == nil {
		return 0, 0, errors.New("租户用户权益数未配置")
	}

	// 统计当前用户总数
	condition := map[string]interface{}{
		"is_deleted": 0,
	}
	userCount, err := s.userRepo.GetUserCount(ctx, condition)
	if err != nil {
		return 0, 0, err
	}

	total := int64(profitAccount.Account) - userCount
	return int64(profitAccount.Account), total, nil
}

func (s *userService) GetAllUserWithOrganization(ctx context.Context) (*basePb.GetAllUserWithOrganizationResponse, error) {
	rootOrganization := &basePb.OrganizationWithUser{}

	// 查询全部组织
	buList, err := s.orgRepo.List(ctx)
	if err != nil {
		return nil, err
	}

	orgIdMap := make(map[int64]*org.GfyOrganizationPo)
	parentGuid2Child := make(map[int64][]*org.GfyOrganizationPo)
	for _, buItem := range buList {
		orgIdMap[buItem.Id] = buItem
		if buItem.ParentId > 0 {
			children, ok := parentGuid2Child[buItem.ParentId]
			if ok {
				children = append(children, buItem)
			} else {
				children = []*org.GfyOrganizationPo{buItem}
			}
			parentGuid2Child[buItem.ParentId] = children
		} else {
			// 根 buguid 暂时不用，只是做冗余
			rootOrganization.OrgName = buItem.Name
			rootOrganization.Id = buItem.Id
		}
	}

	// 查询未禁用的用户
	org2Users := make(map[int64][]*user.GfyxUserPo, 0)
	_, userList, err := s.userRepo.QueryUserList(ctx, map[string]interface{}{"status": constants.UserStatusNormal}, nil, "")
	if err != nil {
		return nil, err
	}

	// 查询用户表 id 对应的组织
	userIds := make([]int64, 0)
	for _, userItem := range userList {
		userIds = append(userIds, userItem.Id)
	}
	UserOrgRelations, err := s.userOrgRepo.GetListByUserIds(ctx, userIds)
	if err != nil {
		return nil, err
	}

	for _, userItem := range userList {
		for _, userOrgRelation := range UserOrgRelations {
			if userOrgRelation.UserId == userItem.Id {
				users, ok := org2Users[userOrgRelation.OrganizationId]
				if ok {
					users = append(users, userItem)
				} else {
					users = []*user.GfyxUserPo{userItem}
				}
				org2Users[userOrgRelation.OrganizationId] = users
			}
		}
	}

	// 树状结构，广度优先
	var nodeList []*basePb.OrganizationWithUser
	nodeList = append(nodeList, rootOrganization)
	for len(nodeList) != 0 {
		var newChildList []*basePb.OrganizationWithUser
		for _, node := range nodeList {
			//1.补充联系人信息
			users, ok := org2Users[node.Id]
			if ok && len(users) > 0 {
				for _, userItem := range users {
					node.Users = append(node.Users, &basePb.UserMiniInfo{
						Id:     userItem.Id,
						Name:   userItem.Name,
						Mobile: userItem.Mobile,
					})
				}
			}
			//2.补充子节点（子bu）
			children, ok := parentGuid2Child[node.Id]
			if ok && len(children) > 0 {
				for _, childNode := range children {
					newChild := &basePb.OrganizationWithUser{
						Id:       childNode.Id,
						OrgName:  childNode.Name,
						ChildOrg: []*basePb.OrganizationWithUser{},
						Users:    []*basePb.UserMiniInfo{},
					}
					newChildList = append(newChildList, newChild)
					node.ChildOrg = append(node.ChildOrg, newChild)
				}
			}
		}
		nodeList = newChildList
	}
	return &basePb.GetAllUserWithOrganizationResponse{RootOrg: rootOrganization}, nil
}

func (s *userService) GetUserInfoByUserGuid(ctx context.Context, userGuid string) (*user.GfyxUserPo, error) {
	_, list, err := s.userRepo.QueryUserList(ctx, map[string]interface{}{"user_guids": []string{userGuid}}, nil, "")
	if err != nil {
		return nil, err
	}

	if len(list) == 0 {
		return nil, nil
	}
	return list[0], nil
}

func (s *userService) GetMyResponsibleAreaUserList(ctx context.Context, request *basePb.GetMyResponsibleAreaUserListRequest) (*basePb.GetMyResponsibleAreaUserListResponse, error) {
	// 1，获取我的用户信息
	loginUser := usermetadata.GetMetaUserInfo(ctx)
	// 2，获取我负责的人用户id
	var userIds []int64
	subUserIds, err := s.userOrgRepo.GetMyResponseOrgUserIds(ctx, loginUser.UserId)
	if err != nil {
		stark.Logger.Errorf(ctx, "GetMyResponsibleAreaUserList error: %v", err)
		return nil, ykerrcode.TogRPCError(errcode.UserOrgResponseOrgUserError, "获取我负责区域联系人失败")
	}
	userIds = append(userIds, subUserIds...)
	subUserIds, err = s.userOrgRepo.GetMyResponseSubOrgUserIds(ctx, loginUser.UserId)
	if err != nil {
		stark.Logger.Errorf(ctx, "GetMyResponseSubOrgUserIds error: %v", err)
		return nil, ykerrcode.TogRPCError(errcode.UserOrgResponseSubOrgUserError, "获取我负责子级区域联系人失败")
	}
	userIds = append(userIds, subUserIds...)
	userIds = utils.RemoveDuplicatesInt64(userIds)
	// 3, 查找用户详细信息
	response := &basePb.GetMyResponsibleAreaUserListResponse{
		Total: 0,
		List:  make([]*basePb.BaseUserOption, 0),
	}
	if len(userIds) > 0 {
		userList, pageInfo, err := s.userRepo.UserList(ctx, userIds, constants.UserStatusNormal, "", &utils.PageInfo{
			PageSize: int(request.PageSize),
			Page:     int(request.Page),
		})
		response.Total = pageInfo.Total
		if err != nil {
			stark.Logger.Errorf(ctx, "UserList error: %v", err)
			return nil, ykerrcode.TogRPCError(errcode.UserListError, "获取用户信息列表失败")
		}
		for _, userItem := range userList {
			userOption := &basePb.BaseUserOption{
				Id:       userItem.Id,
				UserName: userItem.Name,
				Uid:      userItem.Uid,
			}
			response.List = append(response.List, userOption)
		}
	}
	return response, nil
}
